﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace ICSharpCode.WinFormsUI.Controls.NTimeLine
{
    public partial class NTimelineControl : NPanel
    {
        private int position = 0;
        private Padding margin = new Padding(2);
        private Padding padding = new Padding(0);
        private Point drawPositionOffset = new Point();
                
        private Point mouseDownPos = new Point();
        private Point mouseDownOffset = new Point();

        private int smallChange = 32;
        private int largeChange = 32;        

        private int scrollerBarValue = 0;
        private int scrollerBarMinnum = 0;
        private int scrollerBarMaxnum = 100;        
        private int scrollerBarWidth = 6;
        private int scrollerThumbHeight = 40;
        private Boolean scrollerBarVisable = false;
        private Boolean scrollerBarMouseDownState = false;

        private ToolTip toolTip = new ToolTip();        
        private string lastToolTipText = "";
        private string lastSeletedItemTag = "";

        private bool showLoading = false;
        private bool newItemModel = false;
        private bool selectedCursor = false;
        private bool lastSelectedCursor = false;

        private Color titleColor = Color.Black;
        private Color loadingBackColor = Color.White;
        private Color mouseInColor = Color.FromArgb(240, 245, 249);
        private Color linkColor = Color.Blue; 

        private Brush scrollThumbBru = Brushes.Gray;
        private Brush ScrollSlideBru = SystemBrushes.ControlLight;

        private List<MonthItem> _dataList = new List<MonthItem>();
        public List<MonthItem> DataList
        {
            get { return _dataList; }
            set
            {
                _dataList = value;               
            }
        }

        private bool _isEditModel = true;
        public bool IsEditModel
        {
            get { return _isEditModel; }
            set
            {
                _isEditModel = value;
                this.Invalidate();
            }
        }

        public NTimelineControl()
        {
            InitializeComponent();
            InitializeControl();
            SetStyle(ControlStyles.UserPaint | 
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw | 
                ControlStyles.SupportsTransparentBackColor, true);
        }

        private void InitializeControl()
        {
            BorderStyle = NBorderStyle.All;
            BackColor = Color.White;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            DrawContent(e.Graphics);
            DrawScrollBar(e.Graphics);
            base.OnPaint(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            selectedCursor = false;

            string tooltipText = "";
            string seletedItemTag = null;

            if (scrollerBarVisable && scrollerBarMouseDownState)
            {
                DoMouseScrolling(e);
                return;
            }

            //是否继续 当选择项为 DateItem 时 就跳过 DateTimeItem 循环
            bool isChidrenContinueForeach = true;

            if (DataList == null)
                return;

            foreach(MonthItem monthItem in DataList)
            {
                foreach (DateItem dateItem in monthItem.List)
                {
                    if (dateItem.ClickRect.Contains(e.Location))
                    {
                        dateItem.Selected = true;
                        if (_isEditModel)
                        {
                            if (dateItem.AddRect.Contains(e.Location))
                            {
                                selectedCursor = true;
                                if (this.Cursor != Cursors.Hand)
                                {
                                    this.Cursor = Cursors.Hand;
                                }
                            }
                        }
                        seletedItemTag = dateItem.Tag;
                        isChidrenContinueForeach = false;
                    }
                    else
                    {
                        dateItem.Selected = false;
                    }

                    foreach (DateTimeItem dateTimeItem in dateItem.List)
                    {
                        if (isChidrenContinueForeach &&
                            dateTimeItem.ClickRect.Contains(e.Location))
                        {
                            dateTimeItem.Selected = true;
                            if (!_isEditModel)
                            {
                                if (this.Cursor != Cursors.Hand)
                                {
                                    this.Cursor = Cursors.Hand;
                                }
                            }
                            selectedCursor = true;
                            seletedItemTag = dateTimeItem.Tag;
                            if (!string.IsNullOrEmpty(dateTimeItem.ToolTip))
                            {
                                tooltipText = dateTimeItem.ToolTip;
                            }
                            if (_isEditModel && dateTimeItem.EditRect.Contains(e.Location))
                            {
                                if (this.Cursor != Cursors.Hand)
                                {
                                    this.Cursor = Cursors.Hand;
                                }
                                dateTimeItem.ButtonState = 1;
                            }
                            else if (_isEditModel && dateTimeItem.DeleteRect.Contains(e.Location))
                            {
                                if (this.Cursor != Cursors.Hand)
                                {
                                    this.Cursor = Cursors.Hand;
                                }
                                dateTimeItem.ButtonState = 2;
                            }
                            else if (_isEditModel)
                            {
                                if (this.Cursor != Cursors.Default)
                                {
                                    this.Cursor = Cursors.Default;
                                }
                                dateTimeItem.ButtonState = 0;
                            }
                        }
                        else
                        {
                            dateTimeItem.ButtonState = 0;
                            dateTimeItem.Selected = false;
                        }
                    }

                }
            }             

            if (scrollerBarVisable && thumbRect.Contains(e.Location))
            {
                if (this.Cursor != Cursors.Hand)
                {
                    this.Cursor = Cursors.Hand;
                }
                selectedCursor = true;
            }           

            if (newItemModel &&
                newItemRect.Contains(e.Location))
            {
                if (this.Cursor != Cursors.Hand)
                {
                    this.Cursor = Cursors.Hand;
                }
                selectedCursor = true;
            }

            if (tooltipText != lastToolTipText)
                toolTip.SetToolTip(this, tooltipText);

            if (!selectedCursor && this.Cursor != Cursors.Default)
                this.Cursor = Cursors.Default;

            if (lastSeletedItemTag != seletedItemTag)
                this.Invalidate();

            if (newItemModel &&
                lastSelectedCursor != selectedCursor)
                this.Invalidate();

            lastSelectedCursor = selectedCursor;
            lastToolTipText = tooltipText;
            lastSeletedItemTag = seletedItemTag;

        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);

            if (!newItemModel)
            {
                //是否继续 当选择项为 DateItem 时 就跳过 DateTimeItem 循环
                bool isChidrenContinueForeach = true;

                foreach(MonthItem monthItem in DataList)
                {
                    foreach (DateItem dateItem in monthItem.List)
                    {
                        if (dateItem.ClickRect.Contains(e.Location))
                        {
                            var eventArg = new TimeLineEventArgs(dateItem);
                            if (_isEditModel && dateItem.AddRect != Rectangle.Empty && dateItem.AddRect.Contains(e.Location))
                            {
                                eventArg.Command = "new";
                            }
                            DoItemClick(eventArg);
                            isChidrenContinueForeach = false;
                        }
                        foreach (DateTimeItem dateTimeItem in dateItem.List)
                        {
                            if (isChidrenContinueForeach &&
                                dateTimeItem.ClickRect.Contains(e.Location))
                            {
                                var eventArg = new TimeLineEventArgs(dateTimeItem);
                                eventArg.Command = "detail";
                                if (_isEditModel && dateTimeItem.EditRect != Rectangle.Empty && dateTimeItem.EditRect.Contains(e.Location))
                                {
                                    eventArg.Command = "edit";
                                }
                                if (_isEditModel && dateTimeItem.DeleteRect != Rectangle.Empty && dateTimeItem.DeleteRect.Contains(e.Location))
                                {
                                    eventArg.Command = "delete";
                                }
                                DoItemClick(eventArg);
                                isChidrenContinueForeach = false;
                            }

                            if (!isChidrenContinueForeach)
                                break;
                        }

                        if (!isChidrenContinueForeach)
                            break;

                    }
                }
                               
            }
            else
            {
                if (newItemRect.Contains(e.Location))
                {
                    var eventArg = new TimeLineEventArgs(null);
                    eventArg.Command = "new";
                    DoItemClick(eventArg);
                }
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (thumbRect.Contains(e.Location))
                scrollerBarMouseDownState = true;
            mouseDownPos = new Point(e.X, e.Y);
            mouseDownOffset = new Point(thumbRect.X, thumbRect.Y);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            mouseDownPos = new Point(e.X, e.Y);
            scrollerBarMouseDownState = false;
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            AdjustScollerBars();
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            DoMouseWheel(e);
        }

        protected virtual void DoItemClick(TimeLineEventArgs e)
        {
            EventHandler<TimeLineEventArgs> handler = (EventHandler<TimeLineEventArgs>)Events[itemEventObject];
            if (handler != null)
            {
                handler(this, e);
            }
        }

        private Rectangle MeasureItemBound(Graphics g, int index, MonthItem item)
        {
            int itemHeight = 46;
            if (item.List != null)
            {
                foreach (DateItem subItem in item.List)
                {
                    if (subItem.List != null)
                    {
                        foreach(DateTimeItem subsubItem in subItem.List)
                        {
                            itemHeight = itemHeight + 32;
                            if (!string.IsNullOrEmpty(subsubItem.Summary))
                            {
                                itemHeight = itemHeight + 26;
                            }
                        }
                    }
                    itemHeight = itemHeight + 32;
                }               
            }
            Rectangle rect = new Rectangle(drawPositionOffset.X + padding.Left, drawPositionOffset.Y + position, this.Width - padding.Left - padding.Right - (scrollerBarVisable ? 0 : scrollerBarWidth), itemHeight);
            position = position + itemHeight;
            return rect;
        }

        private Rectangle MeasureScrollerBar()
        {
            int borderWidth = 1;
            if(this.BorderStyle == NBorderStyle.None)
            {
                borderWidth = 0;
            }
            return new Rectangle(this.Width - scrollerBarWidth - borderWidth, borderWidth, scrollerBarWidth, this.Height - 2 * borderWidth);
        }

        private void DrawTimelineItem(Graphics g, int index, MonthItem item)
        {
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;

            // margin
            Rectangle bound = item.Bound;
            
            //g.DrawRectangle(new Pen(SystemColors.ControlDark), bound);
            g.DrawLine(new Pen(SystemColors.ControlLight) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dot }, 5, bound.Top + 23, bound.Width - 10, bound.Top + 23);

            Point start = new Point(5 + 18, bound.Top + (index > 0 ? 0 : 5));
            Point end = new Point(5 + 18, bound.Bottom - (index < this.DataList.Count - 1 ? 0 : 5));
            g.DrawLine(new Pen(SystemColors.ControlLight), start, end);

            Rectangle iconRect = new Rectangle(5, bound.Top + 5, 36, 36);
            g.FillEllipse(Brushes.Orange, iconRect);
            g.DrawString(item.DateLabel, this.Font, Brushes.White, iconRect, sf);

            if (item.List != null)
            {
                StringFormat subSf = new StringFormat();
                subSf.LineAlignment = StringAlignment.Center;
                Font subTitleFont = new Font("仿宋", 12, FontStyle.Bold | FontStyle.Italic) { };

                int top = bound.Top + 15;
                for (int i = 0; i < item.List.Count; i++)
                {
                    top = top + 32;
                    DateItem subItem = item.List[i];

                    Rectangle subIconRect = new Rectangle(5 + 12, top + 9, 12, 12);
                    g.FillEllipse(Brushes.Orange, subIconRect);
                    //g.DrawEllipse(new Pen(Color.Orange) { Width=2.0f }, subIconRect);
                    //g.DrawString((i + 1).ToString(), this.Font, Brushes.White, subIconRect, sf);
                    subIconRect.Inflate(-2, -2);
                    g.FillEllipse(Brushes.White, subIconRect);

                    Rectangle subRect = new Rectangle(56, top, bound.Width - 64, 32);
                    if (subItem.Selected)
                    {
                        using (var roundedRectanglePath = CommonHelper.CreateRoundedRectanglePath(subRect, 2))
                        {
                            g.FillPath(new SolidBrush(mouseInColor), roundedRectanglePath);
                        }
                    }

                    Rectangle subTitleRect = new Rectangle(56, top, bound.Width - 64 - 30, 32);
                    //g.DrawRectangle(new Pen(Color.Orange), subTitleRect);
                    //g.DrawString((i + 1) + "、" + subItem.Title, this.Font, Brushes.Red, subTitleRect, subSf);

                    Brush subTitleBrush = new SolidBrush(titleColor);                
                    g.DrawString(subItem.Date.ToString("yyyy-MM-dd"), subTitleFont, subTitleBrush, subTitleRect, subSf);
                    //g.FillRectangle(Brushes.Red, subTitleRect);

                    Rectangle subOptionRect = new Rectangle(bound.X + bound.Width - 34 + 4, top + 8, 16, 16);
                    //g.FillRectangle(Brushes.Yellow, subOptionRect);
                    g.DrawImage(this.TimeLineIcons.Images[2], subOptionRect);
                    subItem.AddRect = subOptionRect;
                    subItem.ClickRect = subRect;

                    if (subItem.List != null)
                    {
                        for (int j = 0; j < subItem.List.Count; j++)
                        {
                            top = top + 32;
                            DateTimeItem subsubItem = subItem.List[j];

                            //Rectangle subsubIconRect = new Rectangle(5 + 14, top + 10, 8, 8);
                            //g.FillEllipse(Brushes.Orange, subsubIconRect);
                            //subsubIconRect.Inflate(-2, -2);
                            //g.FillEllipse(Brushes.White, subsubIconRect);

                            Rectangle DateTimeItemClickRect = new Rectangle(56, top + 2, bound.Width - 64, 28);

                            if (!string.IsNullOrEmpty(subsubItem.Summary))
                                DateTimeItemClickRect = new Rectangle(DateTimeItemClickRect.X, DateTimeItemClickRect.Y, DateTimeItemClickRect.Width, DateTimeItemClickRect.Height + 32);

                            if (subsubItem.Selected)
                            {
                                using (var roundedRectanglePath = CommonHelper.CreateRoundedRectanglePath(DateTimeItemClickRect, 2))
                                {
                                    g.FillPath(new SolidBrush(mouseInColor), roundedRectanglePath);
                                }
                            }

                            Brush drawTitleBrush = new SolidBrush(titleColor);
                            if (subsubItem.Selected)
                                drawTitleBrush = new SolidBrush(linkColor);

                            Color drawTitleColor = titleColor;
                            if (subsubItem.Selected)
                                drawTitleColor = linkColor;

                            if (!subsubItem.Selected)
                            {
                                switch (subsubItem.Level)
                                {
                                    case ImportantLevel.Important:
                                        drawTitleColor = Color.Orange;
                                        break;
                                    case ImportantLevel.MoreImportant:
                                        drawTitleColor = Color.Brown;
                                        break;
                                    case ImportantLevel.MostImportant:
                                        drawTitleColor = Color.Red;
                                        break;
                                }
                            }

                            //Rectangle subsubImgRect = new Rectangle(56 + 0, top + 7, 16, 16);
                            ////g.FillEllipse(Brushes.Red, subsubImgRect);
                            //g.DrawImage(this.TimeLineIcons.Images[2], subsubImgRect);

                            Brush itemIconBrush = Brushes.Red;
                            switch (subsubItem.Timeliness)
                            {
                                case Timeliness.Normal:
                                    itemIconBrush = Brushes.Green;
                                    break;
                                case Timeliness.Yellow:
                                    itemIconBrush = Brushes.Yellow;
                                    break;
                                case Timeliness.Orange:
                                    itemIconBrush = Brushes.Orange;
                                    break;
                                case Timeliness.Red:
                                    itemIconBrush = Brushes.Red;
                                    break;
                                case Timeliness.Dark:
                                    itemIconBrush = Brushes.Gray;
                                    break;
                                case Timeliness.Black:
                                    itemIconBrush = Brushes.Black;
                                    break;
                            }

                            int m = 20;
                            Rectangle subsubImgRect = Rectangle.Empty;
                            if (subsubItem.Icon != null)
                            {
                                if (subsubItem.Icon.Height == 16)
                                {
                                    m = 20;
                                    subsubImgRect = new Rectangle(56 + 0, top + 3, 16, 16);
                                }
                                if (subsubItem.Icon.Height == 24)
                                {
                                    m = 28;
                                    subsubImgRect = new Rectangle(56 + 0, top + 3, 24, 24);
                                } 
                                else
                                {
                                    throw new Exception("只支持16*16、24*24大小的图标");
                                }
                                g.DrawImage(subsubItem.Icon, subsubImgRect);
                            }
                            else
                            {
                                if(!string.IsNullOrEmpty(subsubItem.PersonName))
                                {
                                    m = 28;
                                    subsubImgRect = new Rectangle(56 + 0, top + 3, 24, 24);
                                }
                                else
                                {
                                    m = 20;
                                    subsubImgRect = new Rectangle(56 + 0, top + 7, 16, 16);
                                }                               
                                g.FillEllipse(itemIconBrush, subsubImgRect);

                                if (!string.IsNullOrEmpty(subsubItem.PersonName))
                                {
                                    Brush showNameBrush = Brushes.White;
                                    Font showNameFont = new Font("微软雅黑", 8, FontStyle.Bold);

                                    if (itemIconBrush == Brushes.Red ||
                                        itemIconBrush == Brushes.Yellow)
                                    {
                                        showNameBrush = Brushes.Black;
                                    }

                                    g.DrawString(subsubItem.PersonName, showNameFont, showNameBrush, subsubImgRect, sf);
                                }

                            }

                            //Rectangle subsubTitleRect = new Rectangle(56 + 20, top, bound.Width - 84 - 60, 32);
                            Rectangle subsubTitleRect = new Rectangle(56 + m, top, bound.Width - 84 - 60, 32);
                            //g.DrawRectangle(new Pen(Color.Orange), subsubTitleRect);
                            //g.DrawString((i + 1) + "、" + subItem.Title, this.Font, Brushes.Red, subTitleRect, subSf);
                            //g.DrawString(subsubItem.Title, this.Font, drawTitleBrush, subsubTitleRect, subSf);
                            TextRenderer.DrawText(g, subsubItem.Title, this.Font, subsubTitleRect, drawTitleColor, TextFormatFlags.Left | TextFormatFlags.WordEllipsis | TextFormatFlags.VerticalCenter);

                            if (_isEditModel && subsubItem.Selected)
                            {
                                //绘制删除按扭
                                Size subsubTitleSize = TextRenderer.MeasureText(g, subsubItem.Title, this.Font);
                                int editButtonOffset = subsubTitleRect.X + subsubTitleSize.Width + 2;
                                if (editButtonOffset + 48 > bound.Width)
                                {
                                    editButtonOffset = bound.Width - 48;
                                }
                                subsubItem.EditRect = new Rectangle(editButtonOffset, top + 8, 16, 16);
                                subsubItem.DeleteRect = new Rectangle(editButtonOffset + 16 + 4, top + 8, 16, 16);
                            }

                            Rectangle subsubTimeRect = new Rectangle(bound.Width - 84, top, 76, 32);
                            //g.FillRectangle(Brushes.Green, subsubTimeRect);
                            //g.DrawString((i + 1) + "、" + subItem.Title, this.Font, Brushes.Red, subTitleRect, subSf);
                            g.DrawString(subsubItem.DateTime.ToString("HH:mm:ss"), this.Font, drawTitleBrush, subsubTimeRect, subSf);

                            if (!string.IsNullOrEmpty(subsubItem.Summary))
                            {
                                Font drawSummaryFont = this.Font;
                                Brush drawSummaryBrush = Brushes.Gray;
                                Color drawSummaryColor = Color.Gray;

                                if (subsubItem.Selected)
                                {
                                    drawSummaryBrush = new SolidBrush(SystemColors.ControlDark);
                                    //drawSummaryFont = new Font(this.Font, FontStyle.Italic);
                                    drawSummaryColor = SystemColors.ControlDark;
                                }

                                top = top + 32;
                                Rectangle subsubSummaryRect = new Rectangle(56, top, bound.Width - 64, 26);
                                //g.DrawRectangle(Pens.Red, subsubSummaryRect);
                                //g.DrawString(subsubItem.Summary, drawSummaryFont, drawSummaryBrush, subsubSummaryRect, subSf);
                                TextRenderer.DrawText(g, subsubItem.Summary, drawSummaryFont, subsubSummaryRect, drawSummaryColor, TextFormatFlags.Left | TextFormatFlags.WordEllipsis | TextFormatFlags.VerticalCenter);

                            }

                            subsubItem.ClickRect = DateTimeItemClickRect;

                            g.DrawLine(new Pen(SystemColors.ControlLight) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dot }, 56, top + 32, bound.Width - 10, top + 32);

                            if (_isEditModel && subsubItem.Selected)
                            {
                                //switch (subsubItem.ButtonState)
                                //{
                                //    case 1:
                                //        g.FillRectangle(new SolidBrush(Color.Orange), subsubItem.EditRect);
                                //        g.FillRectangle(new SolidBrush(Color.FromArgb(240, 245, 249)), subsubItem.DeleteRect);
                                //        break;
                                //    case 2:
                                //        g.FillRectangle(new SolidBrush(Color.FromArgb(240, 245, 249)), subsubItem.EditRect);
                                //        g.FillRectangle(new SolidBrush(Color.Orange), subsubItem.DeleteRect);
                                //        break;
                                //    default:
                                //        g.FillRectangle(new SolidBrush(Color.FromArgb(240, 245, 249)), subsubItem.EditRect);
                                //        g.FillRectangle(new SolidBrush(Color.FromArgb(240, 245, 249)), subsubItem.DeleteRect);
                                //        break;
                                //}

                                g.FillRectangle(new SolidBrush(mouseInColor), subsubItem.EditRect);
                                g.FillRectangle(new SolidBrush(mouseInColor), subsubItem.DeleteRect);

                                //绘制编辑按扭
                                g.DrawImage(this.TimeLineIcons.Images[0], subsubItem.EditRect);
                                //绘制删除按扭
                                g.DrawImage(this.TimeLineIcons.Images[1], subsubItem.DeleteRect);
                            }                            

                        }
                    }                   

                }

            }

            StringFormat sf2 = new StringFormat();
            sf2.LineAlignment = StringAlignment.Center;
            Rectangle itemTitleRect = new Rectangle(56, bound.Top + 5, bound.Width - 64, 36);
            //g.DrawRectangle(new Pen(Color.Orange), itemTitleRect);
            //g.DrawString("共计 " + (item.List == null ? 0 : item.List.Count()) + " 个事项", this.Font, Brushes.Black, itemTitleRect, sf2);

        }

        private void DrawTimelineItems(Graphics g)
        {
            position = 0;                       
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            if (DataList != null)
            {
                for (int index = 0; index < DataList.Count; index++)
                {
                    MonthItem item = DataList[index];
                    item.Bound = MeasureItemBound(g, index, item);
                    if (IsRectangleVisible(item.Bound))
                    {
                        DrawTimelineItem(g, index, item);
                    }
                }
            }         

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
        }

        private void DrawContent(Graphics g)
        {
            newItemModel = false;
            if (_isEditModel &&
                (this.DataList == null || this.DataList.Count == 0))
            {
                newItemModel = true;
            }

            if (!showLoading)
            {
                if (newItemModel)
                    DrawNewItem(g);
                else
                    DrawTimelineItems(g);
            }
            else
            {
                DrawLoading(g);
            }
        }

        private void DrawNewItem(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.HighQuality;
            Rectangle clientRect = new Rectangle(0, 0, this.Width, this.Height);
            Rectangle drawRect = new Rectangle(clientRect.X + 10, clientRect.Y + (clientRect.Height - 30) / 2, clientRect.Width - 20, 30);
            //g.FillRectangle(new SolidBrush(BackColor), clientRect);
            Brush backfillBrush = Brushes.Green;
            if (selectedCursor)
            {
                backfillBrush = new SolidBrush(Color.FromArgb(0, 153, 0));
            }
            using (var path = CommonHelper.CreateRoundedRectanglePath(drawRect, 8))
            {
                g.FillPath(backfillBrush, path);
            }

            newItemRect = new Rectangle(clientRect.X + 10, clientRect.Y + (clientRect.Height - 30) / 2, clientRect.Width - 20, 30);

            SizeF newItemTextSize = g.MeasureString(" 新建待办事项 ", this.Font);

            Rectangle newItemIconRect = new Rectangle(newItemRect.X + (int)((newItemRect.Width - newItemTextSize.Width - 16 - 4) / 2), newItemRect.Y + 8, 16, 16);
            g.DrawImage(this.TimeLineIcons.Images[5], newItemIconRect);

            Rectangle newItemTextRect = new Rectangle(newItemRect.X + (int)((newItemRect.Width - newItemTextSize.Width - 16 - 8) / 2) + 16 + 8, newItemRect.Y, (int)newItemTextSize.Width, 30);

            TextRenderer.DrawText(g, "新建待办事项", this.Font, newItemTextRect, Color.White, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis);
            g.SmoothingMode = SmoothingMode.Default;

        }

        private void DrawLoading(Graphics g)
        {
            Rectangle clientRect = new Rectangle(1, 1, this.Width - 2, this.Height - 2);
            Rectangle loadRect = new Rectangle(clientRect.X + 10, clientRect.Y + (clientRect.Height - 30) / 2, clientRect.Width - 20, 30);
            g.FillRectangle(new SolidBrush(BackColor), clientRect);
            using (var path = CommonHelper.CreateRoundedRectanglePath(loadRect, 8))
            {
                g.FillPath(new SolidBrush(loadingBackColor), path);
            }
            TextRenderer.DrawText(g, "数据加载中...", this.Font, loadRect, titleColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis);
        }

        private void DrawScrollBar(Graphics g)
        {
            if (!scrollerBarVisable)
                return;
            DrawScrollSlide(g);
            DrawScrollThumb(g);
        }

        Rectangle thumbRect = new Rectangle();
        Rectangle scrollerRect = new Rectangle();
        Rectangle newItemRect = new Rectangle();

        private int MaxnumHeight
        {
            get
            {
                int maxnum = 0;
                Graphics g = null;
                if (this.DataList != null)
                {
                    for (int i = 0; i < this.DataList.Count; i++)
                    {
                        var item = this.DataList[i];
                        maxnum += MeasureItemBound(g, i, item).Height;
                    }
                }
                return maxnum;
            }
        }

        private int GetThumbHeight()
        {
            int disHeight = this.BorderStyle == NBorderStyle.None ? this.Height : this.Height - 2;
            if (MaxnumHeight == 0 || MaxnumHeight <= disHeight) return disHeight;
            int thumbHeight = (int)(disHeight * 1.0d / MaxnumHeight * disHeight);
            if (thumbHeight < 20) thumbHeight = 20;
            largeChange = DisplayRectangle.Height - thumbHeight;
            return thumbHeight;
        }

        private bool IsRectangleVisible(Rectangle bound)
        {
            bool isItemDrawModel = true;
            if (bound.Bottom < this.DisplayRectangle.Top ||
                        bound.Top > this.DisplayRectangle.Bottom)
            {
                isItemDrawModel = false;
            }
            return isItemDrawModel;
        }

        private void DrawScrollSlide(Graphics g)
        {
            scrollerRect = MeasureScrollerBar();
            g.FillRectangle(ScrollSlideBru, scrollerRect);
        }

        private void DrawScrollThumb(Graphics g)
        {
            int thumbOffsetY = (int)(scrollerBarValue * 1.0 / scrollerBarMaxnum * (scrollerRect.Height - thumbRect.Height));
            thumbRect = new Rectangle(scrollerRect.X, scrollerRect.Y + thumbOffsetY, scrollerRect.Width, scrollerThumbHeight);
            g.FillRectangle(scrollThumbBru, thumbRect);
        }

        private void AdjustScollerBars()
        {
            scrollerBarValue = 0;
            scrollerBarVisable = false;
            drawPositionOffset = new Point(0, 0);
            scrollerThumbHeight = GetThumbHeight();
            if (MaxnumHeight > Height)
            {
                scrollerBarVisable = true;
            }
        }

        private void DoMouseWheel(MouseEventArgs e)
        {
            if (!scrollerBarVisable)
                return;

            int olePositionOffsetY = drawPositionOffset.Y;

            int mouseWheelScrollLines = e.Delta / NativeMethods.WHEEL_DELTA;

            int newPositionOffsetY = drawPositionOffset.Y + mouseWheelScrollLines * smallChange;

            int d = newPositionOffsetY - olePositionOffsetY;
            scrollerBarValue += (int)(-d * 1.0 / (MaxnumHeight + smallChange - this.Height) * scrollerBarMaxnum);

            if (scrollerBarValue < 0)
            {
                scrollerBarValue = 0;               
            }
            if (scrollerBarValue > 100)
            {
                scrollerBarValue = 100;                
            }

            int drawOffsetY = (int)(-scrollerBarValue * 1.0 / scrollerBarMaxnum * (MaxnumHeight + smallChange - this.Height));
            drawPositionOffset = new Point(0, drawOffsetY);

            this.Invalidate();
        }

        private void DoMouseScrolling(MouseEventArgs e)
        {
            if (!scrollerBarVisable)
                return;

            int d = mouseDownOffset.Y + e.Location.Y - mouseDownPos.Y;
            scrollerBarValue = (int)(d * 1.0 / (scrollerRect.Height - thumbRect.Height) * scrollerBarMaxnum);

            if (scrollerBarValue < 0)
            {
                scrollerBarValue = 0;                
            }
            if (scrollerBarValue > 100)
            {
                scrollerBarValue = 100;                
            }

            int drawOffsetY = (int)(-scrollerBarValue * 1.0 / scrollerBarMaxnum * (MaxnumHeight + smallChange - this.Height));
            drawPositionOffset = new Point(0, drawOffsetY);

            this.Invalidate();

        }

        public string ToDateLabel(DateTime dateTime)
        {
            return DateTimeUtils.ToDateLabel(dateTime);
        }

        public void StartShowLoading()
        {
            showLoading = true;
            this.Invalidate();
        }

        public void EndShowLoading()
        {
            showLoading = false;
            this.Invalidate();
        }

        public void DataBind()
        {
            AdjustScollerBars();
            this.Invalidate();
        }

        private static readonly object itemEventObject = new object();      
        /// <summary>
        /// 
        /// </summary>
        public new event EventHandler<TimeLineEventArgs> Click
        {
            add { Events.AddHandler(itemEventObject, value); }
            remove { Events.RemoveHandler(itemEventObject, value); }
        }

        public void SetTheme(string themeName)
        {
            switch (themeName)
            {
                case "Default":                    
                    titleColor = Color.Black;
                    linkColor = Color.Blue;
                    BackColor = Color.FromArgb(255, 255, 255);
                    loadingBackColor = SystemColors.Control;
                    mouseInColor = Color.FromArgb(240, 245, 249);
                    break;
                case "Black":
                    titleColor = Color.FromArgb(240, 240, 240);
                    linkColor = Color.FromArgb(083, 153, 205);
                    BackColor = Color.FromArgb(030, 030, 030);
                    loadingBackColor= Color.FromArgb(045, 045, 048);
                    mouseInColor = Color.FromArgb(045, 045, 048);
                    break;
            }
        }

    }
}
